#ifndef _GRAPHE_
#define _GRAPHE_

#include <iostream>
#include <cstring>

#include "structure.hpp"
#include "noeud.hpp"
#include "arc.hpp"

using namespace std;

struct graphe {
    Noeud ** noeuds;
    int nb_noeuds;
    int capa_noeuds;

    Arc ** arcs;
    int nb_arcs;
    int capa_arcs;
};

/*
    Pour toutes les fonctions si dessous, la variable verbose permet d'afficher des information
    supplémentaires lors de l'éxecution, principalement utiles au débuggage
*/

graphe* initGraphe (bool verbose = false);
/*  Initialise un graphe vide
    Postconditions :
        * renvoie un graphe initialisé vide
*/

void ajoutNoeud (graphe *g, char * nomNoeud, bool verbose = false);
/*  crée et ajoute un noeud au graphe
    Préconditions :
        * g initialisé
    Postconditions :
        * g contient un nouveau noeud avec pour nom la chaine nomNoeud
        * si le tableau de noeuds doit être agrandis, la fonction s'en occupe
*/

void ajoutNoeud (graphe *g, Noeud *n, bool verbose = false);
/*  ajoute un noeud au graphe
    Préconditions :
        * g initialisé
        * n initialisé
    Postconditions :
        * n est rattaché au graphe
        * si le tableau de noeuds doit être agrandis, la fonction s'en occupe
*/

void agrandirNoeuds (graphe *g, bool verbose = false);
/*  agrandi le tableau de noeuds si besoin
    Préconditions :
        * g initialisé
    Postconditions :
        * le tableau de noeuds est aggrandis si il a autant d'élements que sa capacité
*/

int suppressionNoeud(graphe *g, char * nomNoeud, bool verbose = false);
/*  supprime un noeud du graphe
    Préconditions :
        * g initialisé
        * nomNoeud le nom à donner au nouveau noeud
    Postconditions :
        * le noeud donc le nom est nomNoeud est supprimé et libéré en mémoire
        * les arcs reliés à ce noeud sont supprimés et libérés en mémoire
        * si le noeud est supprimé la fonction renvoie 0
        * si il n'y a pas de noeuds de ce nom, la fonction renvoie 1
        * si le tableau de noeuds doit être réduit, la fonction s'en occupe
*/


int suppressionNoeud(graphe *g, Noeud *n, bool verbose = false);
/*  supprime un noeud du graphe
    Préconditions :
        * g initialisé
        * n initalisé
    Postconditions :
        * le noeud est supprimé et libéré en mémoire
        * les arcs reliés à ce noeud sont supprimés et libérés en mémoire
        * si le noeud est supprimé la fonction renvoie 0
        * si ce noeud n'existe pas dans le graphe, il n'est pas supprimé et la fonction renvoie 1
        * si le tableau de noeuds doit être réduit, la fonction s'en occupe
*/

Noeud * rechercheNoeud(graphe *g, char * rech, bool verbose = false);
/*  cherche un noeud par son nom
    Préconditions :
        * g initialisé
    Postconditions :
        * renvoie le pointeur sur le noeud ayant le nom rech
        * renvoie pointeur nul si ce noeud n'existe pas
*/

void ajoutArc (graphe *g, char * src, char * dst, int valeur, bool verbose = false);
/*  crée et ajoute un arc au graphe ou modifie la valeur d'un arc déjà existant
    Préconditions :
        * g initialisé
        * src et dst sont respectivement les noms des noeuds source et destination du noeud
    Postconditions :
        * crée et ajoute un arc au graphe si les deux noeud existene et que cet arc n'existait pas encore
        * met a jour la valeur si l'arc existait déjà
*/

void ajoutArc (graphe *g, Arc *a, bool verbose = false);
/*  ajoute un arc au graphe ou modifie la valeur d'un arc déjà existant
    Préconditions :
        * g initialisé
        * a initialisé
    Postconditions :
        * ajoute l'arc a au graphe
        * si l'arc a à la même source et le même destinataire qu'un arc du graphe, sa valeur est mise à jour
*/

void agrandirArcs (graphe *g, bool verbose = false);
/*  agrandis le tableau d'arcs du graphe si besoin
    Préconditions :
        * g initialisé
    Postconditions :
        * le tableau d'arcs est aggrandis si il a autant d'élements que sa capacité
*/

int suppressionArc(graphe *g, char * src, char * dst, bool verbose = false);
/*  supprime un arc du graphe
    Préconditions :
        * g initialisé
        * src et dst sont respectivements la source et la destination de l'arc a supprimer
    Postconditions :
        * l'arc possédant la source src et la destination dst est supprimée du graphe et libéré et mémoire
        * si l'arc est supprimé la fonction renvoie 0
        * si il n'y a pas d'arc de ce nom, la fonction renvoie 1
        * si le tableau d'arcs doit être réduit, la fonction s'en occupe
*/

int suppressionArc(graphe *g, Arc *a, bool verbose = false);
/*  supprime un arc du graphe
    Préconditions :
        * g initialisé
        * a initialisé
    Postconditions :
        * l'arc a est supprimée et libéré en mémoire
        * si l'arc est supprimé la fonction renvoie 0
        * si cet arc n'existe pas dans le graphe, l'arc a n'est pas supprimé et la fonction renvoie 1
        * si le tableau d'arcs doit être réduit, la fonction s'en occupe
*/

Arc * rechercheArc(graphe *g, char * src, char * dst, bool verbose = false);
/*  cherche un arc par le nom de sa source et de sa destination
    Préconditions :
        * g initialisé
    Postconditions :
        * renvoie le pointeur sur l'arc ayant une source portant le nom src et un destinataire portant le nom dst
        * renvoie un pointeur nul si cet arc n'existe pas
*/

void afficherGraphe (graphe *g, bool verbose = false);
/*  affiche un graphe
    Préconditions :
        * g initialisé
    Postconditions :
        * les noeuds du graphes sont affichés
*/

void testamentGraphe (graphe *g);
/*  supprime et libére un graphe en mémoire
    Préconditions :
        * g initialisé
    Postconditions :
        * le graphe ainsi que tous ce noeuds et arcs sont supprimés et libérés en mémoire
*/

#endif // _GRAPHE_

